﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using log4net;
using Microsoft.Practices.Prism.Events;
using Reactor.Entities;
using Reactor.MiniManager.Events;
using Reactor.MiniManager.ViewModels;
using Reactor.Providers;
using Reactor.ServiceGrid;
using Samurai.Wakizashi.Workflow;

namespace Reactor.MiniManager.Workflows
{
    public class CoreHealthCheckWorkflow : SequentialWorkflow<CoreHealthCheckWorkflow.WorkflowContext>
    {
        private readonly ICoreDataProvider _coreDataProvider;
        private static readonly ILog Log = LogManager.GetLogger(typeof(CoreHealthCheckWorkflow));

        /// <summary>
        /// Initializes a new instance of the <see cref="CoreHealthCheckWorkflow"/> class.
        /// </summary>
        /// <param name="healthCheckInterval">The health check interval.</param>
        /// <param name="reactorCoreViewModels">The reactor core view models.</param>
        /// <param name="coreDataProvider">The core data provider.</param>
        public CoreHealthCheckWorkflow(TimeSpan healthCheckInterval, ObservableCollection<ReactorCoreViewModel> reactorCoreViewModels, ICoreDataProvider coreDataProvider)
        {
            if (reactorCoreViewModels == null) throw new ArgumentNullException("reactorCoreViewModels");
            if (coreDataProvider == null) throw new ArgumentNullException("coreDataProvider");

            _coreDataProvider = coreDataProvider;

            Context = new WorkflowContext
            {
                HealthCheckInterval = healthCheckInterval,
                ReactorCoreViewModels = reactorCoreViewModels
            };
            WorkflowFailed += ServiceHealthCheckWorkflow_WorkflowFailed;
            LoopWorkflow = true;

            RegisterSteps();
        }

        private void RegisterSteps()
        {
            RegisterStep(CheckCoreDataRecords, ThreadType.Task);
            RegisterStep(RefreshServiceStatuses, ThreadType.Ui);
            Suspend(Context.HealthCheckInterval);
        }

        internal void CheckCoreDataRecords()
        {
            Context.Entities = _coreDataProvider.GetAllCores();
        }

        internal void RefreshServiceStatuses()
        {
            foreach (var reactorCoreViewModel in Context.ReactorCoreViewModels)
            {
                var vm = reactorCoreViewModel;
                var core = (from c in Context.Entities
                            where c.Identifier.Name == vm.Name
                                  && c.Identifier.Version == vm.Version
                            select c).FirstOrDefault();

                if (core == null)
                    ProcessMissingCoreRecord(new ServiceIdentifier {Name = vm.Name, Version = vm.Version});
                else
                    vm.LastSeen = core.LastSeen;
            }

            Context.Entities = null;
        }

        private void ProcessMissingCoreRecord(ServiceIdentifier serviceIdentifier)
        {
            
        }

        private void ServiceHealthCheckWorkflow_WorkflowFailed(object sender, WorkflowCompletedEventArgs<WorkflowContext> e)
        {
            Context.EventAggregator.GetEvent<CoreHealthCheckWorkflowFailed>().Publish(null);
        }

        #region Nested Types

        public class WorkflowContext : IWorkflowContext
        {
            public IEnumerable<ReactorCoreEntity> Entities { get; set; }
            public ObservableCollection<ReactorCoreViewModel> ReactorCoreViewModels { get; set; }
            public TimeSpan HealthCheckInterval { get; set; }
            public IEventAggregator EventAggregator { get; set; }
        }

        #endregion
    }
}
